require 'rubygems'
require 'raspell'

class SpellCheck < AbstarctPhraseLevelAnalysis

  def _pre_layer_global(directory, experimentalData, phraseCards)
    @learning_curves = {}
    @regression_fits = {}  
  end
  
  def _post_layer_global(directory, experimentalData, phraseCards)
    confident_level = 0.95
    null_hypo = "Mean of Regression Slope using Layer 1 \= Layer 2"
    alter_hypo = "Mean of Regression Slope using Layer 1 > Layer 2 (less negative)"
    
    text = "2 Sample t-test <br/>" +
           "Null Hypothesis: #{null_hypo}<br/>" +
           "Alternative Hypothesis: #{alter_hypo}  <br/>" +
           "Confidence Level: #{confident_level} <br/><br/>" 
             
       
    report = Report.new(directory, "ttest")
    
    text += "<table border=\"1\">"+
            "<thead>"+
            "<tr>" +
            "<td>Set</td><td>p-value</td><td>t-value</td>" +
            "<td>Mean of Layer1</td><td>Mean of Layer2</td>" +
            "</tr>" +
            "</thead><tbody>"
    
    # create a R instance
    r = RSRuby.instance
      
    [1,2,3,4].each do |i|
      curve1 = @learning_curves[1][(1..i)]
      curve2 = @learning_curves[2][(1..i)]
      t = r.t_test(:x => curve1, :y => curve2, :alternative => "greater", 
        :var_equal => false, :conf_level => confident_level)
      
      text += "<tr>"
      text += "<td><b> #{i==1 ? "" : "1 - "} #{i}</b></td>"
      text += "<td>#{t["p.value"]}</td>"
      text += "<td>#{t["statistic"]["t"]}</td>"
      text += "<td>#{t["estimate"]["mean of x"]}</td>"
      text += "<td>#{t["estimate"]["mean of y"]}</td>"
      text += "</tr>"  
    end
    
    text += "</tbody></table><br/>"
    report.new_section("t-test",text)
    report.to_html
    
    # ALL Slopes
    g = _create_graph("Regression Slopes in Typo", "Phrases", "Counts (Normalized)")
    g.hide_legend = true

    fits1 = @regression_fits[1]
    fits2 = @regression_fits[2]
    g.dot_radius = 1
    g.line_width = 1
    fits1.each_pair {|k,v| g.data k, v, "#ff0000"}
    fits2.each_pair {|k,v| g.data k, v, "#0000ff"}

    report.new_section("Regression Slopes",  nil, g, "all_slopes.png")
    report.to_html
  end  
    
  def _pre_subject_global(directory, experimentalData, phraseCards, layer, entries)
    @learning_curve = {}
    @regression_fit = {}    
  end
  
  def _post_subject_global(directory, experimentalData, phraseCards, layer, entries)
    @learning_curves[layer] = @learning_curve
    @regression_fits[layer] = @regression_fit

    report = Report.new(directory, "Statistics")
    text = "<table border=\"1\">"+
           "<thead>"+
           "<tr>" +
           "<td>Set</td><td>Regression Slope</td><td>Average</td>" +
           "<td>Standard Deviation</td><td>Variance</td>" +
           "</tr>" +
           "</thead><tbody>"
           
    # for each segment
    [1,2,3,4].each do |i|
      text += "<tr>"
      curve = @learning_curve[(1..i)] 

      text += "<td><b>1..#{i}</b></td>"
      text += "<td>#{curve.nil? ? "" : curve.inspect}</td>"
      text += "<td>#{curve.nil? ? "" : average(curve)}</td>"
      text += "<td>#{curve.nil? ? "" : standard_deviation(curve)}</td>"
      text += "<td>#{curve.nil? ? "" : variance(curve)}</td>"
      text += "</tr>"
    end
    text += "</tbody></table><br/>"
    report.new_section("Regression Slope",text)
    report.to_html
  end
  
  def _perform_analysis(report, uid, sbj_entries, experimentalData, phraseCards)
   all_data = []
   regression_data = []  
   data_by_set = {}

   sbj_entries.each do |e|
     #initialize if nil
     data_by_set[e.set] ||= []
     data_by_set[e.set] << e
   end

   
   #do some simple statistics
   stat = ""

   #Generate a section for each set  
   experimentalData.get_sets(uid).each do |i|
     #create a graph for each set
     g = _create_graph("Spelling Mistakes (Subject:#{uid})", "Phrases", "Counts (Normalized)")
        
     entries = data_by_set[i]
     entries.sort! { |x,y| x.date <=> y.date }
      
     sp_err_counts = entries.collect do |e|
       _spelling_error_count(e)
     end
     all_data.concat sp_err_counts
           
     g.data "Subject:#{uid} Set:#{i}", sp_err_counts
     
     #Compute the learning curve for each set
     regression = LinearRegression.new(sp_err_counts)
     @learning_curve[i] ||= []
     @learning_curve[i] << regression.slope
             
     g.data "Regression", regression.fit
     regression_data.concat regression.fit
     
     avg = average(sp_err_counts)
     
     stat = "<b>Average: </b> #{avg} <br/>" + 
            "<b>Regression Slope: </b> #{regression.slope} </br>"                
     report.new_section("Set #{i}", stat, g, "%02d%04d%02d.png"%[experimentalData.get_layer(uid),uid,i])
     
      # acc. regression
      # 10*i = set: 1-i
      regression = LinearRegression.new(all_data)
      @learning_curve[(1..i)] ||= []
      @learning_curve[(1..i)] << regression.slope
   end  
    
   g = _create_graph("Spelling Mistakes (ALL)", "Phrases", "Counts (Normalized)")
   g.data "Subject:#{uid} All set", all_data


   #Compute the learning curve for all set
   regression = LinearRegression.new(all_data)
   @learning_curve["all"] ||= []
   @learning_curve["all"] << regression.slope       
     
   g.data "Regression", regression.fit   

   avg = average(all_data)    
   stat = "<b>Average: </b> #{avg} <br/>" + 
          "<b>Regression Slope: </b> #{regression.slope} </br>"         
   report.new_section("ALL", stat, g, "%02d%04d_all.png"%[experimentalData.get_layer(uid),uid])
   
    #draw the regression slopes of all set
    g = _create_graph("BS Count (ALL)", "Phrase", "Time (10ms)")
    g.data "Subject:#{uid} All set", all_data
    g.data "Regression", regression_data
    report.new_section("ALL Set 2", nil, g, "%02d%04d_all2.png"%[experimentalData.get_layer(uid),uid])
    
    @regression_fit[uid] = regression_data
 end
 
  
  
  def _get_string(e)
    s = ""
    e.sequence.each do |seq|
      if ( seq[0].eql?("\b"))
        s.chop!
      else
        s = s + seq[0]
      end
    end
    
    return s
  end  
  
  def _spelling_error_count(e)
    count = 0
    s = _get_string(e).split
    
    speller = Aspell.new("en_US")
    
    s.each do |word|
      count += 1 if !speller.check(word)
    end
    
    return s.length ==0 ? 0 : count.to_f/s.length
  end
  
end